/*
 * @Author: 李佳宣 2186459656@qq.com
 * @Date: 2025-06-27 10:17:39
 * @LastEditors: 李佳宣 2186459656@qq.com
 * @LastEditTime: 2025-06-29 10:46:14
 * @FilePath: \23\Calculator.java
 */

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

// 自定义按钮类 - 确保颜色完全渲染并处理悬停/按下效果
class ColoredButton extends JButton {
    private Color backgroundColor;         // 按钮背景颜色
    private Color foregroundColor;         // 按钮前景颜色(文本颜色)
    
    // 构造函数，接收按钮文本、背景色和前景色
    public ColoredButton(String text, Color backgroundColor, Color foregroundColor) {
        super(text);                       // 调用父类JButton的构造函数
        this.backgroundColor = backgroundColor;
        this.foregroundColor = foregroundColor;
        init();                            // 初始化按钮设置
    }
    
    // 初始化按钮属性和样式
    private void init() {
        // 确保按钮完全不透明，以便显示背景色
        setOpaque(true);
        // 启用内容区域填充
        setContentAreaFilled(true);
        // 启用边框绘制
        setBorderPainted(true);
        // 设置背景色和前景色
        setBackground(backgroundColor);
        setForeground(foregroundColor);
        // 禁用焦点绘制(按钮被选中时的虚线框)
        setFocusPainted(false);
        // 设置复合边框: 外部1像素灰色边框，内部10像素空白边距
        setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(Color.GRAY, 1),
            BorderFactory.createEmptyBorder(10, 10, 10, 10)
        ));
    }
    
    // 重写按钮绘制方法，处理不同状态下的颜色显示
    @Override
    protected void paintComponent(Graphics g) {
        // 处理按钮按下状态 - 使用更深的颜色
        if (getModel().isPressed()) {
            g.setColor(backgroundColor.darker());
        } 
        // 处理鼠标悬停状态 - 使用更亮的颜色
        else if (getModel().isRollover()) {
            g.setColor(backgroundColor.brighter());
        } 
        // 正常状态 - 使用默认背景色
        else {
            g.setColor(backgroundColor);
        }
        // 填充整个按钮区域
        g.fillRect(0, 0, getWidth(), getHeight());
        // 调用父类方法绘制按钮文本和其他元素
        super.paintComponent(g);
    }
}

// 音频播放器类 - 负责背景音乐播放
class AudioPlayer {
    private AudioClip backgroundMusic;     // 背景音乐剪辑
    private boolean isPlaying = false;     // 播放状态标志
    // 直接指定音频文件路径
    private static final String SOUND_PATH = "C:\\Users\\jiaxuan\\Desktop\\23\\_- 主动 (1).wav";
    
    // 构造函数，初始化音频播放器
    public AudioPlayer() {
        try {
            backgroundMusic = loadSound(SOUND_PATH);
        } catch (Exception e) {
            System.err.println("背景音乐加载失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    // 加载音频文件并返回AudioClip对象
    private AudioClip loadSound(String fileName) {
        try {
            File file = new File(fileName);
            if (!file.exists()) {
                System.out.println("音频文件不存在: " + fileName);
                return null;
            }
            
            URL soundUrl = file.toURI().toURL();
            System.out.println("正在加载音频: " + soundUrl);
            return Applet.newAudioClip(soundUrl);
        } catch (MalformedURLException e) {
            System.err.println("音频URL格式错误: " + fileName);
            e.printStackTrace();
            return null;
        }
    }
    
    // 播放背景音乐(循环播放)
    public void playBackgroundMusic() {
        if (backgroundMusic != null && !isPlaying) {
            backgroundMusic.loop();        // 循环播放音频
            isPlaying = true;              // 更新播放状态
            System.out.println("背景音乐已播放");
        } else if (backgroundMusic == null) {
            System.out.println("无法播放音乐: 音频未加载");
        }
    }
    
    // 停止背景音乐播放
    public void stopBackgroundMusic() {
        if (backgroundMusic != null && isPlaying) {
            backgroundMusic.stop();        // 停止音频播放
            isPlaying = false;             // 更新播放状态
        }
    }
    
    // 检查是否正在播放音乐
    public boolean isPlaying() {
        return isPlaying;
    }
}

// 主计算器类，继承自JFrame并实现ActionListener接口
public class Calculator extends JFrame implements ActionListener {
    private JPanel leftPanel, rightPanel;  // 左右分栏面板
    private JPanel north, center;          // 左侧计算器内部面板(顶部和中部)
    private JTextField field;              // 计算显示文本框
    private JButton[] btns;                // 按钮数组
    private JTextArea guideTextArea;       // 功能说明文本区
    private AudioPlayer audioPlayer;       // 音频播放器实例
    private Font defaultFont;              // 系统可用的默认字体

    // 构造函数，初始化计算器界面
    public Calculator() {
        // 强制使用Metal外观风格，确保按钮颜色正常显示
        try {
            UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
        } catch (Exception e) {
            e.printStackTrace();           // 打印异常信息
        }
        
        // 检测系统可用的中文字体
        defaultFont = detectChineseFont();
        
        setTitle("计算器");     // 设置窗口标题
        setSize(900, 700);                 // 设置窗口大小
        setDefaultCloseOperation(EXIT_ON_CLOSE); // 设置关闭操作
        setLocationRelativeTo(null);       // 居中显示窗口
        
        // 创建音频播放器实例
        audioPlayer = new AudioPlayer();
        
        // 在Swing事件调度线程中初始化UI和播放音乐
        SwingUtilities.invokeLater(() -> {
            initComponent();                   // 初始化界面组件
            audioPlayer.playBackgroundMusic(); // 播放背景音乐
            setVisible(true);                  // 显示窗口
        });
    }
    
    // 检测系统中可用的中文字体，确保文本正常显示
    private Font detectChineseFont() {
        // 按优先级排列的中文字体列表
        String[] preferredFonts = {
            "Microsoft YaHei", "SimHei", "WenQuanYi Micro Hei", 
            "Heiti TC", "PingFang SC", "SimSun"
        };
        
        // 获取系统图形环境
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        // 获取系统可用字体列表
        String[] availableFonts = ge.getAvailableFontFamilyNames();
        
        // 遍历首选字体列表，查找系统中存在的字体
        for (String fontName : preferredFonts) {
            for (String available : availableFonts) {
                if (available.equalsIgnoreCase(fontName)) {
                    // 找到匹配字体后创建并返回Font对象
                    return new Font(fontName, Font.PLAIN, 12);
                }
            }
        }
        
        // 如果没有找到任何中文字体，回退到系统默认对话框字体
        return new Font(Font.DIALOG, Font.PLAIN, 12);
    }
 
    // 初始化界面组件
    private void initComponent() {
        // 创建左右分栏主面板
        leftPanel = new JPanel(new BorderLayout());  // 左侧计算器面板
        rightPanel = new JPanel(new BorderLayout()); // 右侧功能说明面板
        
        // 创建左侧计算器的顶部面板(用于显示计算结果)
        north = new JPanel();
        field = new JTextField();                  // 创建文本输入框
        field.setPreferredSize(new Dimension(500, 150)); // 设置文本框大小
        field.setEditable(false);                  // 设置为不可编辑
        // 设置文本框字体(使用检测到的中文字体)
        field.setFont(defaultFont.deriveFont(Font.BOLD, 35f));
        north.add(field);                          // 将文本框添加到顶部面板
        
        // 创建左侧计算器的中部面板(用于放置按钮)
        center = new JPanel();
        center.setLayout(new GridLayout(5, 4));    // 设置为5行4列的网格布局
        
        // 创建并初始化所有按钮(使用自定义ColoredButton类)
        btns = new JButton[20];
        // 第一行按钮: 7, 8, 9, +
        btns[0] = new ColoredButton("7", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[1] = new ColoredButton("8", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[2] = new ColoredButton("9", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[3] = new ColoredButton("+", new Color(135, 206, 235), new Color(50, 50, 50));
        
        // 第二行按钮: 4, 5, 6, -
        btns[4] = new ColoredButton("4", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[5] = new ColoredButton("5", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[6] = new ColoredButton("6", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[7] = new ColoredButton("-", new Color(135, 206, 235), new Color(50, 50, 50));
        
        // 第三行按钮: 1, 2, 3, ×
        btns[8] = new ColoredButton("1", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[9] = new ColoredButton("2", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[10] = new ColoredButton("3", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[11] = new ColoredButton("×", new Color(135, 206, 235), new Color(50, 50, 50));
        
        // 第四行按钮: 0, ., =, ÷
        btns[12] = new ColoredButton("0", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[13] = new ColoredButton(".", new Color(220, 235, 245), new Color(50, 50, 50));
        btns[14] = new ColoredButton("=", new Color(144, 238, 144), new Color(50, 50, 50));
        btns[15] = new ColoredButton("÷", new Color(135, 206, 235), new Color(50, 50, 50));
        
        // 第五行按钮: C, B, T, S
        btns[16] = new ColoredButton("C", new Color(255, 182, 118), new Color(50, 50, 50));
        btns[17] = new ColoredButton("B", new Color(255, 192, 203), new Color(50, 50, 50));
        btns[18] = new ColoredButton("T", new Color(221, 160, 221), new Color(50, 50, 50));
        btns[19] = new ColoredButton("S", new Color(255, 255, 200), new Color(50, 50, 50));
        
        // 设置所有按钮的字体并添加到中部面板
        for (JButton btn : btns) {
            btn.setFont(defaultFont.deriveFont(Font.BOLD, 25f));
            center.add(btn);
        }
        
        // 初始化右侧功能说明面板
        guideTextArea = new JTextArea();
        guideTextArea.setText(
            "功能键目录说明：\n\n" +
            "■ 数字键（0-9）：输入数字\n" +
            "■ 运算符键（+、-、×、÷）：执行加减乘除运算\n" +
            "■ 小数点（.）：输入小数点\n" +
            "■ 等号（=）：执行计算并显示结果\n" +
            "■ 清除键（C）：清空当前输入\n" +
            "■ 退格键（B）：删除最后输入的字符\n" +
            "■ 时间键（T）：显示当前系统时间\n" +
            "■ 随机数键（S）：生成1-100的随机整数\n\n" +
            "【操作提示】\n" +
            "1. 支持连续运算（如：3+4×5=23）\n" +
            "2. 时间键可实时刷新当前时间\n" +
            "3. 随机数键每次点击生成新数值"
        );
        guideTextArea.setEditable(false);      // 设置为不可编辑
        guideTextArea.setFont(defaultFont.deriveFont(Font.PLAIN, 16f)); // 设置字体
        guideTextArea.setBackground(new Color(245, 245, 255)); // 设置背景色
        // 将文本区放入滚动面板，以便内容超出时可滚动
        JScrollPane scrollPane = new JScrollPane(guideTextArea);
        rightPanel.add(scrollPane, BorderLayout.CENTER); // 添加到右侧面板
        
        // 组装左侧计算器面板
        leftPanel.add(north, BorderLayout.NORTH);
        leftPanel.add(center, BorderLayout.CENTER);
        
        // 创建分割面板，实现左右分栏
        JSplitPane splitPane = new JSplitPane(
            JSplitPane.HORIZONTAL_SPLIT,     // 水平分割
            leftPanel,                       // 左侧组件
            rightPanel                       // 右侧组件
        );
        splitPane.setDividerLocation(500);   // 设置分割线位置
        splitPane.setOneTouchExpandable(true); // 添加快速展开/折叠按钮
        
        // 将分割面板添加到主窗口
        getContentPane().add(splitPane);
        
        // 为所有按钮添加事件监听器
        for (JButton btn : btns) {
            btn.addActionListener(this);
        }
    }
 
    // 处理按钮点击事件
    private void setBtnText(String text) {
        String currentText = field.getText(); // 获取当前文本框内容
        
        // 处理小数点前补0的情况
        if (text.equals(".") && (currentText.isEmpty() || isOperator(currentText.charAt(currentText.length() - 1)))) {
            currentText += "0";              // 前面补0
            field.setText(currentText);      // 更新文本框
        }
        
        // 防止操作符和小数点连续出现
        if ((isOperator(text.charAt(0)) || text.equals(".")) && 
            !currentText.isEmpty() && 
            (isOperator(currentText.charAt(currentText.length() - 1)) || currentText.endsWith("."))) {
            return;                        // 如果重复则不执行任何操作
        }
        
        // 防止操作符出现在数字前面
        if (isOperator(text.charAt(0)) && currentText.isEmpty()) {
            return;                        // 不允许操作符开头
        }
        
        // 处理时间键功能
        if (text.equals("T")) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
            field.setText(dateFormat.format(new Date())); // 显示当前时间
            return;
        }
        
        // 处理随机数键功能
        if (text.equals("S")) {
            Random random = new Random();
            int randomNum = random.nextInt(100) + 1; // 生成1-100的随机数
            field.setText(String.valueOf(randomNum)); // 显示随机数
            return;
        }
        
        // 处理其他按钮逻辑
        switch (text) {
            case "C":                      // 清除键
                field.setText("");         // 清空文本框
                break;
            case "B":                      // 退格键
                if (!currentText.isEmpty()) {
                    // 删除最后一个字符
                    field.setText(currentText.substring(0, currentText.length() - 1));
                }
                break;
            case "=":                      // 等号键
                calculate();               // 执行计算
                break;
            default:                       // 其他按钮(数字和运算符)
                field.setText(currentText + text); // 追加文本
                break;
        }
    }

    // 执行数学表达式计算
    private void calculate() {
        String expression = field.getText(); // 获取当前表达式
        // 将乘除符号替换为JavaScript可识别的符号
        expression = expression.replace("×", "*");
        expression = expression.replace("÷", "/");
        
        // 创建JavaScript脚本引擎
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("javascript");
        try {
            // 执行表达式计算
            Object result = engine.eval(expression);
            field.setText(result.toString()); // 显示计算结果
        } catch (ScriptException e) {
            field.setText("运算错误");        // 显示错误信息
            e.printStackTrace();             // 打印异常堆栈
        }
    }

    // 判断字符是否为操作符
    private boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '×' || c == '÷';
    }

    // 实现ActionListener接口的方法，处理按钮点击事件
    @Override
    public void actionPerformed(ActionEvent a) {
        if (a.getSource() instanceof JButton) {
            JButton btn = (JButton) a.getSource();
            setBtnText(btn.getText());       // 处理按钮文本
        }
    }

    // 主方法，程序入口点
    public static void main(String[] args) {
        // 设置系统属性，强制使用Unicode字体渲染
        System.setProperty("awt.useSystemAAFontSettings", "on");
        System.setProperty("swing.aatext", "true");
        
        // 在事件调度线程中创建和显示GUI
        SwingUtilities.invokeLater(Calculator::new);
    }
}